#include "stdafx.h"
#include "time.h"

#include "../../graphical_environment/GraphicalMap.hpp"

#include "../../environment/Map.hpp"

namespace core
{

	Application * Application::m_currentApplication = NULL;

    //-------------------------------------------------------------------------------------
    //Constructor / Destructor
    //-------------------------------------------------------------------------------------

    Application::Application() :
    m_windowName(L"AGA Application"),
    m_continue(true),
    m_device(NULL),
    m_driver(NULL),
    m_sceneManager(NULL),
    m_guiEnv(NULL)
    {
		m_currentApplication = this;
    }

    Application::~Application()
    {
		if ( m_currentApplication == this )
			m_currentApplication = NULL;
    }

    void Application::go()
    {
        try
        {
            if (!init())
                return;

            // In order to do framerate independent movement, we have to know
            // how long it was since the last frame
            irr::u32 then = m_device->getTimer()->getTime();

            while (m_device->run ())
            {
                //if ( m_device->isWindowActive() )
                {
                    // Work out a frame delta time.
                    const irr::u32 now = m_device->getTimer()->getTime();
                    const irr::f32 frameDeltaTime = (irr::f32)(now - then) / 1000.f; // Time in seconds
                    then = now;

                    update(frameDeltaTime);
                }
                /*else
                {
                    m_device->yield();
                }*/
            }

            destroy();
        }
        catch (std::exception &e)
        {
            std::cerr << "An exception has occured: " << e.what() << std::endl;
        }
    }

    //-------------------------------------------------------------------------------------
    //Init / Destroy
    //-------------------------------------------------------------------------------------

    bool Application::init()
    {
        // The event manager work as the event receiver, so we have to create it first
        Event::EventManager::createSingleton();

        // We try to initialise Irrlicht, if the initialisation fails, we just quit
        if (!initialiseIrrlicht())
            return false;

        srand(time(NULL));

        initialiseManagers();

        initialiseScene();

        // we connect the quit signal to stop the application
        CONNECT(Event::EVENT_QUIT_APPLICATION, &Application::onReceiveQuitApplication);

        return true;
    }                  // on affiche le rendu

    bool Application::destroy()
    {
        Event::EventManager::getSingleton().destroyAllConnections(this);

        destroyManagers();

        m_device->drop();

        return true;
    }

    void Application::onReceiveQuitApplication(boost::shared_ptr<Event::EventBase> _evt)
    {
        m_continue = false;
    }

    bool Application::initialiseIrrlicht()
    {
#ifdef WIN32
        irr::video::E_DRIVER_TYPE driverType = irr::video::EDT_DIRECT3D9;
#else
        irr::video::E_DRIVER_TYPE driverType = irr::video::EDT_OPENGL;
#endif
        m_device = irr::createDevice(    // creation du device
          driverType,
          irr::core::dimension2d<irr::u32>(WINDOW_WIDTH,WINDOW_HEIGHT),
          irr::u32(32),false,false,false,
          Event::EventManager::getSingletonPtr());

        if ( !m_device )
            return false;

        m_device->setWindowCaption(m_windowName.c_str());

        m_driver = m_device->getVideoDriver();
	    m_sceneManager = m_device->getSceneManager();
        m_guiEnv = m_device->getGUIEnvironment();

        return true;
    }

    bool Application::initialiseManagers()
    {
		//environment::Map::createSingleton()->Init();
		graphicalenvironment::GraphicalMap::createSingleton()->Init();
		network::SBSession::create();

        return true;
    }

    bool Application::initialiseScene()
    {
        m_sceneManager->addCameraSceneNode(	0,
                                            irr::core::vector3df(0, 600, MAP_HEIGHT*MAP_TILE_SIZE/2.0f),
                                            irr::core::vector3df(MAP_WIDTH*MAP_TILE_SIZE/2.0f, 0, MAP_HEIGHT*MAP_TILE_SIZE/2.0f) 
                                            );

//        environment::Map::getSingleton().Init();
       // graphicalenvironment::GraphicalMap::getSingleton().Init();

        return true;
    }

    bool Application::destroyManagers()
    {        
        graphicalenvironment::GraphicalMap::destroySingleton();
       // environment::Map::destroySingleton();

        Event::EventManager::destroySingleton();

        return true;
    }

    //-------------------------------------------------------------------------------------
    //System Update
    //-------------------------------------------------------------------------------------

    void Application::update(float _time)
    {
		/*
        static float timeCycle = 0.0f;

		if( timeCycle > CYCLE_MILLISECOND/* = 1 secondes )
		{
			timeCycle = 0;
            //environment::Map::getSingleton().nextCycle();
		}
        timeCycle += (_time * 1000.0f);
		*/
		
        //environment::Map::getSingleton().Update();

        m_driver->beginScene (true, true,
		   irr::video::SColor (255,0,0,0));

        updateManagers(_time);

        m_sceneManager->drawAll ();
        m_guiEnv->drawAll();

        m_driver->endScene ();  
    }

    void Application::updateManagers(float _time)
    {
        Event::EventManager::getSingleton().update(_time);

        graphicalenvironment::GraphicalMap::getSingleton().Update(m_driver);
    }

} // namespace core
